package tech.lq0.dreamaticvoyage.block.entity;

import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;

public abstract class AbstractUCEProviderBlockEntity extends BlockEntity {

    // 最大连接距离
    protected final int range;
    // 最大连接数量
    protected final int maxConnectCount;
    // 已连接的列表
    protected NonNullList<byte[]> connections = NonNullList.create();

    public AbstractUCEProviderBlockEntity(BlockEntityType<?> pType, BlockPos pPos, BlockState pBlockState, int range, int maxConnectCount) {
        super(pType, pPos, pBlockState);
        this.range = range;
        this.maxConnectCount = maxConnectCount;
    }

    abstract protected void transferEnergy(Level pLevel, BlockPos pPos);

    abstract boolean canBeCharged(BlockEntity energySource);

    public boolean canBind(byte[] offset) {
        return Math.abs(offset[0]) <= this.range && Math.abs(offset[1]) <= this.range && Math.abs(offset[2]) <= this.range;
    }

    public boolean canBindMore() {
        return this.connections.size() < this.maxConnectCount;
    }

    public boolean hasConnection(byte[] offset) {
        return this.connections.stream().anyMatch(c -> Arrays.equals(c, offset));
    }

    public void addConnection(byte[] offset) {
        if (this.hasConnection(offset)) {
            return;
        }
        this.connections.add(offset);
    }

    public void removeConnection(byte[] offset) {
        this.connections.removeIf(c -> Arrays.equals(c, offset));
    }

    public NonNullList<byte[]> getConnections() {
        return this.connections;
    }

    @Override
    public void load(CompoundTag pTag) {
        super.load(pTag);
        var connectionsTag = pTag.getList("Connections", CompoundTag.TAG_COMPOUND);
        this.connections.clear();
        for (var connectionTag : connectionsTag) {
            this.connections.add(((CompoundTag) connectionTag).getByteArray("Offset"));
        }
    }

    @Override
    protected void saveAdditional(CompoundTag pTag) {
        super.saveAdditional(pTag);
        var connectionsTag = new ListTag();
        for (var connection : this.connections) {
            var connectionTag = new CompoundTag();
            connectionTag.putByteArray("Offset", connection);
            connectionsTag.add(connectionTag);
        }
        pTag.put("Connections", connectionsTag);
    }

    @Nullable
    @Override
    public Packet<ClientGamePacketListener> getUpdatePacket() {
        return ClientboundBlockEntityDataPacket.create(this);
    }

    @Override
    public CompoundTag getUpdateTag() {
        CompoundTag compoundtag = new CompoundTag();
        var connectionsTag = new ListTag();
        for (var connection : this.connections) {
            var connectionTag = new CompoundTag();
            connectionTag.putByteArray("Offset", connection);
            connectionsTag.add(connectionTag);
        }
        compoundtag.put("Connections", connectionsTag);
        return compoundtag;
    }
}
